package com.hksj.data.event.listener;

import cn.hutool.core.lang.UUID;
import com.alibaba.fastjson.JSONObject;
import com.hksj.data.event.WriteRawTdengineDataEvent;
import com.hksj.data.mapper.DevicePropertyMapper;
import com.hksj.data.service.DevicePropertyService;
import com.hksj.data.tdengine.annatation.ReflectUtil;
import com.hksj.data.tdengine.annatation.Tags;
import com.hksj.data.tdengine.annatation.Values;
import com.hksj.data.tdengine.entity.DeviceLog;
import com.hksj.data.tdengine.operation.TDengineOperations;
import com.hksj.data.thing.RawData;
import com.hksj.data.vo.DefinedDeviceMetadataVO;
import org.influxdb.dto.Point;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author zengke
 * @version 1.0
 * @see WriteRawTdengineDataEventListener
 * @since 2025/08/15 10:23
 */
@Component
public class WriteRawTdengineDataEventListener {

    @Autowired(required = false)
    private TDengineOperations tDengineOperations;

    @Autowired
    private DevicePropertyMapper devicePropertyMapper;

    @Async
    @EventListener
    public void onWriteRawTdengineDataEvent(WriteRawTdengineDataEvent event) {

        //获取原始数据
        RawData data = event.getData();

        //获取上报时间戳
        Long timestamp = data.getTimestamp();

        //获取设备id
        String deviceId = data.getDeviceId();

        //判断设备id是否为空
        if (deviceId == null){
            return;
        }

        //获取数据集合
        Map<String, Object> dataMap = data.getDataMap();

        //判断数据集合是否为空
        if (dataMap == null){
            return;
        }

        //根据设备id查询设备元数据列表
        List<DefinedDeviceMetadataVO> deviceMetadataVOList = devicePropertyMapper.queryDefinedDeviceMetadataList(Collections.singletonList(deviceId));

        //设备元数据列表是否存在
        if (ObjectUtils.isEmpty(deviceMetadataVOList)){
            return;
        }

        //根据设备id进行分组
        Map<String, DefinedDeviceMetadataVO> deviceMetadataMap = deviceMetadataVOList.stream().collect(Collectors.toMap(DefinedDeviceMetadataVO::getDeviceInstanceId, Function.identity()));

        //创建设备日志对象
        DeviceLog deviceLog = new DeviceLog();

        //设置设备日志对象的各属性值
        deviceLog.setDeviceId(deviceId);
        deviceLog.setId(UUID.fastUUID().toString());
        deviceLog.setType("reportProperty");
        deviceLog.setContent(JSONObject.toJSONString(dataMap));
        deviceLog.setCreateTime(timestamp.doubleValue());
        deviceLog.setTimestamp(timestamp.doubleValue());

        //获取设备元数据信息
        DefinedDeviceMetadataVO deviceMetadataVO = deviceMetadataMap.get(deviceId);

        //获取设备日志对象的tags集合
        Map<String, String> tagsMap = ReflectUtil.getFieldMapAnnotatedWith(deviceLog, Tags.class).entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, entry -> String.valueOf(entry.getValue())));

        //获取设备日志对象的values集合
        Map<String, Object> valuesMap = ReflectUtil.getFieldMapAnnotatedWith(deviceLog, Values.class);

        //构建Point点位对象
        Point point = Point.measurement(getDeviceLogStableName(deviceMetadataVO.getProductId()))
                .tag(tagsMap)
                .fields(valuesMap)
                .time(timestamp, TimeUnit.MILLISECONDS)
                .build();

        //写入数据
        tDengineOperations.forWrite().write(point);
    }

    public String getDeviceLogStableName(String productId){
        return "device_log_" + productId;
    }
}
